using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace GameForKids
{

    public class XuLyCongThuc 
    {

        protected string trungto ="";
        protected string congthuc = "";
        protected Stack<Char> toantu = new Stack<char>();
        protected List<string> hauto = new List<string>();
        protected int _n;
        protected int _t;
        protected int _l;

        public XuLyCongThuc()
        {

        }
        // tra ve so diem
        public string TinhDiem(String CongThuc, int N, int T, int L)
        {

            _n = N;
            _t = T;
            _l = L;
            congthuc = CongThuc;
            congthuc = ChuyenHam(congthuc);
            congthuc = ChenThem(congthuc);
            if (congthuc[0] == '-')
                congthuc = "0" + congthuc;
            trungto = "0+" + congthuc + "+";
            InfixToPostfix();
            return tinh();
        }

        // bo bot cac ten ham, quy ve 1 ki tu
        public string ChuyenHam(string CongThuc)
        {
            		int i;
                    for (i = 0; i < CongThuc.Length; i++)
                    {
                        try
                        {
                            if (CongThuc[i] == 's' && CongThuc[i + 1] == 'i' && CongThuc[i + 2] == 'n')
                            {
                                CongThuc = CongThuc.Substring(0, i + 1) + CongThuc.Substring(i + 3);
                            }
                            else if (CongThuc[i] == 'c' && CongThuc[i + 1] == 'o' && CongThuc[i + 2] == 's')
                            {
                                CongThuc = CongThuc.Substring(0, i + 1) + CongThuc.Substring(i + 3);
                            }
                            else if (CongThuc[i] == 't' && CongThuc[i + 1] == 'a' && CongThuc[i + 2] == 'n')
                            {
                                CongThuc = CongThuc.Substring(0, i + 1) + CongThuc.Substring(i + 3);
                            }
                            else if (CongThuc[i] == 's' && CongThuc[i + 1] == 'q' && CongThuc[i + 2] == 'r' && CongThuc[i + 3] == 't')
                            {
                                CongThuc = CongThuc.Substring(0, i) + CongThuc.Substring(i + 2, 1) + CongThuc.Substring(i + 4);
                            }
                        }
                        catch 
                        {
                        }
                    }
            return CongThuc;
        }

        // them cac vi tri de may tinh de hieu
        public string ChenThem(String CongThuc)
        {
            int i = 0;

            for (i = 1; i < CongThuc.Length; i++)
            {
                if (CongThuc[i] == 's' || CongThuc[i] == 'c' ||
                    CongThuc[i] == 't' || CongThuc[i] == 'r' ||
                    CongThuc[i] == 'N' || CongThuc[i] == 'T')
                {
                    if ((CongThuc[i - 1] <= '9' && CongThuc[i - 1] >= '0')
                        || CongThuc[i - 1] == ')' || CongThuc[i - 1] == 'N'
                        || CongThuc[i - 1] == 'T' || CongThuc[i - 1] == 'L')
                    {
                        CongThuc = CongThuc.Substring(0, i) + "*" + CongThuc.Substring(i);
                        i += 1;
                    }
                }
            }

            
            for (i = 0; i < CongThuc.Length; i++)
            {
                try
                {
                    if (CongThuc[i] == '(')
                    {
                        if (CongThuc[i + 1] == '-')
                        {
                            CongThuc = CongThuc.Substring(0, i + 1) + "0" + CongThuc.Substring(i + 1);
                        }
                        else
                        {
                            CongThuc = CongThuc.Substring(0, i + 1) + "0+" + CongThuc.Substring(i + 1);
                        }
                    }
                }
                catch 
                { }

                if (CongThuc[i] == 'N')
                {
                    CongThuc = CongThuc.Substring(0, i)+_n.ToString() + CongThuc.Substring(i+1);
                }
                if (CongThuc[i] == 'T')
                {
                    CongThuc = CongThuc.Substring(0, i) + _t.ToString() + CongThuc.Substring(i + 1);
                }
                if (CongThuc[i] == 'L')
                {
                    CongThuc = CongThuc.Substring(0, i) + _l.ToString() + CongThuc.Substring(i + 1);
                }
            }
            
            return CongThuc;
        }

        // the hien do uu tien cua cac phep tinh
        public int Ma(string s)
        {
            if (s.Equals("s") || s.Equals("c") || s.Equals("t") || s.Equals("r") || s.Equals("^"))
            {
                return 3;
            }
            if (s.Equals("+") || s.Equals("-"))
            {
                return 1;
            }
            if (s.Equals("*") || s.Equals("/"))
            {
                return 2;
            }

           return 0;
        }

        // so sanh xem phep toan nao duoc uu tien hon
        public int SoSanhPT(string s1, string s2)
        {
            if (Ma(s1) > Ma(s2))
            {
                return 1;
            }
            if (Ma(s1) == Ma(s2))
            {
                return 0;
            }
            return -1;
        }





        // tra ve ket qua cac phep toan
        public double GanToanHang(string s, string th1, string th2)
        {
            if (s.Equals("s")) return Math.Sin(double.Parse(th1));
            if (s.Equals("c")) return Math.Cos(double.Parse(th1));
            if (s.Equals("t")) return Math.Tan(double.Parse(th1));
            if (s.Equals("r")) return Math.Sqrt(double.Parse(th1));
            if (s.Equals("+")) return (double.Parse(th1) + double.Parse(th2));
            if (s.Equals("-")) return (double.Parse(th1) - double.Parse(th2));
            if (s.Equals("*")) return (double.Parse(th1) * double.Parse(th2));
            if (s.Equals("/")) return (double.Parse(th1) / double.Parse(th2));
            if (s.Equals("^")) return HamSoMu(double.Parse(th1), int.Parse(th2));
            return 0;
        }

        // tinh ham so mu

        public double HamSoMu(double a, int b)
        {
            if (b < 0)
                return 0;
            if (b == 0)
                return 1;
            if (a == 0)
                return 0;
            if (b % 2 == 0)
                return HamSoMu(a * a, b / 2);
            else
                if (b % 2 == 1)
                    return a * HamSoMu(a * a, b / 2);
            return 0;
        }
        //Ham chuyen doi bieu thuc trung to -> bieu thuc hau to 
        public void InfixToPostfix()
        {
            int i = 1;
            int k = 0;
            do
            {
                //duyet den toan hang
                if (((trungto[i] >= '0') && (trungto[i] <= '9')) &&
                    ((trungto[i - 1] == '+') || (trungto[i - 1] == '-') ||
                    (trungto[i - 1] == '*') || (trungto[i - 1] == '/') ||
                    (trungto[i - 1] == '^') ||(trungto[i - 1] == '(') ))
                {
                    k = i;
                }
                if (((trungto[i] >= '0') && (trungto[i] <= '9')) &&
                    ((trungto[i + 1]== '+') || (trungto[i + 1] == '-') ||
                    (trungto[i + 1] == '*') || (trungto[i + 1] == '/') ||
                    (trungto[i + 1] == '^') || (trungto[i + 1] == ')') ))
                {
                    hauto.Add(trungto.Substring(k,i+1-k));
                }

                //Duyet den toan tu 
                if ((trungto[i] == '+') || (trungto[i] == '-') ||
                    (trungto[i] == '*') || (trungto[i] == '/') ||
                    (trungto[i] == '^') || 
                    (trungto[i] == 's') || (trungto[i] == 'c') ||
                    (trungto[i] == 't') || (trungto[i] == 'r') )
                {
                    if (toantu.Count == 0)
                    {
                        toantu.Push(trungto[i]);
                    }
                    else
                    {
                        while (SoSanhPT(toantu.Peek().ToString(), trungto[i].ToString()) == 1)
                        {
                            hauto.Add(toantu.Pop().ToString());
                        }
                        toantu.Push(trungto[i]);
                    }
                }

                //Neu duyet den ky tu "("
                if (trungto[i] == '(')
                {
                    toantu.Push('(');
                }

                //Neu duyet den ky tu ")"
                if (trungto[i] == ')')
                {
                    do
                    {
                        hauto.Add(toantu.Pop().ToString());
                    }
                    while (!toantu.Peek().ToString().Equals("("));
                    toantu.Pop();
                }
                i += 1;
            } while (i < (trungto.Length - 1));

            do
            {
                hauto.Add(toantu.Pop().ToString());
            } 
            while (toantu.Count!=0);

        } 




        // tinh diem
        public String tinh()
	{
		Stack<String> toanhang = new Stack<String>();
		int i = 0;
		String tmp;
		do
		{

                tmp = hauto[i].ToString();
                if ((tmp[0] <= '9') && (tmp[0] >= '0'))
                {
                    toanhang.Push(tmp);
                }
                if (tmp[0] == '+' || tmp[0] == '-' || tmp[0] == '*' || tmp[0] == '/' || tmp[0] == '^')
                {
                    String th1 = toanhang.Pop().ToString();
                    String th2 = toanhang.Pop().ToString();
                    double th3 = GanToanHang(tmp, th2, th1);
                    toanhang.Push(th3.ToString());
                }
                if (tmp[0] == 's' || tmp[0] == 'c' || tmp[0] == 't' || tmp[0] == 'r')
                {
                    String th1 = toanhang.Pop().ToString();
                    double th3 = GanToanHang(tmp, th1, "not value");
                    toanhang.Push(th3.ToString());
                }
                i += 1;
		} while (i < hauto.Count - 1);
		return (toanhang.Peek().ToString());
	}
    }
}
